<template>
  <div class="markdown-renderer" v-html="renderedContent"></div>
</template>

<script setup lang="ts">
import { computed, onMounted, nextTick, watch } from 'vue'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import 'highlight.js/styles/github.css'

interface Props {
  content: string
  isStreaming?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  content: '',
  isStreaming: false
})

// 配置 markdown-it
const md = new MarkdownIt({
  html: true,        // 允许HTML标签
  breaks: true,      // 将换行符转换为<br>
  linkify: true,     // 自动转换URL为链接
  typographer: true, // 启用一些语言中性的替换和引号美化
  highlight: function (str: string, lang: string) {
    // 确保字符串不为空
    if (!str || str.trim() === '') {
      return ''
    }
    
    // 清理字符串，移除多余的空白
    const cleanStr = str.trim()
    
    // 流式数据处理：优化实时高亮逻辑
    if (props.isStreaming) {
      // 对于流式内容，即使很短也要尝试高亮，确保代码块能够实时区分
      // 但需要处理可能的语法不完整情况
      if (lang && hljs.getLanguage(lang)) {
        try {
          // 对于流式内容，使用更宽松的高亮策略
          return hljs.highlight(cleanStr, { language: lang }).value
        } catch (err) {
          // 如果指定语言失败，尝试自动检测
          try {
            return hljs.highlightAuto(cleanStr).value
          } catch (autoErr) {
            // 如果自动检测也失败，返回原始内容但保持代码块结构
            return cleanStr
          }
        }
      }
      
      // 如果没有指定语言，尝试自动检测
      try {
        return hljs.highlightAuto(cleanStr).value
      } catch (err) {
        return cleanStr
      }
    }
    
    // 非流式内容的正常高亮处理
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(cleanStr, { language: lang }).value
      } catch (err) {
        console.error('代码高亮失败:', err)
        // 如果指定语言失败，尝试自动检测
        try {
          return hljs.highlightAuto(cleanStr).value
        } catch (autoErr) {
          return cleanStr
        }
      }
    }
    
    // 如果没有指定语言，尝试自动检测
    try {
      return hljs.highlightAuto(cleanStr).value
    } catch (err) {
      return cleanStr
    }
  }
})

// 渲染Markdown内容
const renderedContent = computed(() => {
  if (!props.content) return ''
  
  try {
    let content = props.content
    
    // 流式数据处理：确保代码块能够实时高亮
    if (props.isStreaming) {
      // 处理不完整的代码块，确保在流式过程中也能正确显示
      content = processStreamingCodeBlocks(content)
    }
    
    return md.render(content)
  } catch (error) {
    console.error('Markdown渲染失败:', error)
    return props.content.replace(/\n/g, '<br>')
  }
})

// 处理流式代码块
const processStreamingCodeBlocks = (content: string): string => {
  // 检测是否包含代码块标记
  const hasCodeBlocks = content.includes('```')
  
  if (!hasCodeBlocks) {
    return content
  }
  
  // 使用更智能的代码块处理逻辑，特别针对多文件流式输出
  let result = ''
  let currentPos = 0
  let inCodeBlock = false
  let currentLang = ''
  
  // 使用更精确的正则表达式来匹配代码块开始标记
  const codeBlockPattern = /```(\w+)?\n?/g
  let match
  
  while ((match = codeBlockPattern.exec(content)) !== null) {
    const matchStart = match.index
    const matchEnd = match.index + match[0].length
    
    if (!inCodeBlock) {
      // 开始新的代码块
      result += content.slice(currentPos, matchStart)
      
      // 提取语言标识
      currentLang = match[1] || ''
      
      if (currentLang) {
        result += `\`\`\`${currentLang}\n`
      } else {
        result += '```'
      }
      
      inCodeBlock = true
      currentPos = matchEnd
    } else {
      // 结束当前代码块
      const codeContent = content.slice(currentPos, matchStart)
      
      // 检查代码内容是否为空或只有空白字符
      if (codeContent.trim()) {
        // 有实际代码内容，正常闭合代码块
        result += codeContent + '```\n'
      } else {
        // 空代码块，可能是流式过程中的中间状态
        // 保持代码块开放，让后续内容继续添加
        result += codeContent
      }
      
      inCodeBlock = false
      currentLang = ''
      currentPos = matchEnd
    }
  }
  
  // 处理最后一部分内容
  if (inCodeBlock) {
    // 代码块未闭合，这是流式过程中的正常状态
    // 保持代码块开放，让markdown-it能够正确处理
    const remainingContent = content.slice(currentPos)
    result += remainingContent
  } else {
    result += content.slice(currentPos)
  }
  
  return result
}

// 增强的代码块检测函数，专门处理多文件流式输出
const detectCodeBlockState = (content: string) => {
  const codeBlocks = []
  const codeBlockRegex = /```(\w+)?\n?([\s\S]*?)(?=```|$)/g
  let match
  
  while ((match = codeBlockRegex.exec(content)) !== null) {
    const lang = match[1] || ''
    const code = match[2] || ''
    const isComplete = match[0].trim().endsWith('```')
    
    codeBlocks.push({
      lang,
      code: code.trim(),
      isComplete,
      startIndex: match.index,
      endIndex: match.index + match[0].length
    })
  }
  
  return codeBlocks
}

// 添加代码复制功能
onMounted(() => {
  nextTick(() => {
    addCopyButtons()
  })
})

// 监听内容变化，重新添加复制按钮
watch(() => props.content, () => {
  nextTick(() => {
    addCopyButtons()
  })
})

const addCopyButtons = () => {
  const codeBlocks = document.querySelectorAll('.markdown-renderer pre code')
  
  codeBlocks.forEach((codeBlock) => {
    const pre = codeBlock.parentElement
    if (pre && !pre.querySelector('.copy-button')) {
      const copyButton = document.createElement('button')
      copyButton.className = 'copy-button'
      copyButton.innerHTML = '复制'
      copyButton.onclick = () => copyCode(codeBlock.textContent || '')
      
      pre.style.position = 'relative'
      
      // 为流式代码块添加特殊样式
      if (props.isStreaming) {
        pre.classList.add('streaming')
        
        // 添加语言标识
        const lang = pre.getAttribute('data-lang') || 
                   codeBlock.className.match(/language-(\w+)/)?.[1] || ''
        if (lang) {
          pre.setAttribute('data-lang', lang)
        }
      }
      
      pre.appendChild(copyButton)
    }
  })
}

const copyCode = async (text: string) => {
  try {
    await navigator.clipboard.writeText(text)
    // 可以添加复制成功的提示
    console.log('代码已复制到剪贴板')
  } catch (err) {
    console.error('复制失败:', err)
  }
}
</script>

<style scoped>
.markdown-renderer {
  line-height: 1.6;
  word-break: break-word;
}

:deep(pre) {
  position: relative;
  background: #f6f8fa;
  border: 1px solid #e1e4e8;
  border-radius: 6px;
  padding: 16px;
  margin: 8px 0;
  overflow-x: auto;
  font-family: 'SFMono-Regular', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
  font-size: 13px;
  line-height: 1.45;
}

:deep(pre code) {
  background: none;
  padding: 0;
  border-radius: 0;
  font-size: inherit;
  color: #24292e;
  white-space: pre;
  word-wrap: normal;
}

/* 代码高亮样式增强 */
:deep(.hljs) {
  background: #f6f8fa !important;
  color: #24292e;
  border-radius: 6px;
  padding: 16px;
  overflow-x: auto;
  font-family: 'SFMono-Regular', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
  font-size: 13px;
  line-height: 1.45;
}

:deep(.copy-button) {
  position: absolute;
  top: 8px;
  right: 8px;
  background: #0969da;
  color: white;
  border: none;
  border-radius: 4px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  opacity: 0;
  transition: all 0.2s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

:deep(pre:hover .copy-button) {
  opacity: 1;
}

:deep(.copy-button:hover) {
  background: #0550ae;
  transform: translateY(-1px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}

:deep(h1), :deep(h2), :deep(h3), :deep(h4), :deep(h5), :deep(h6) {
  margin-top: 24px;
  margin-bottom: 16px;
  font-weight: 600;
  line-height: 1.25;
}

:deep(h1) {
  font-size: 2em;
  border-bottom: 1px solid #eaecef;
  padding-bottom: 0.3em;
}

:deep(h2) {
  font-size: 1.5em;
  border-bottom: 1px solid #eaecef;
  padding-bottom: 0.3em;
}

:deep(h3) {
  font-size: 1.25em;
}

:deep(p) {
  margin-bottom: 16px;
}

:deep(ul), :deep(ol) {
  margin-bottom: 16px;
  padding-left: 2em;
}

:deep(li) {
  margin-bottom: 0.25em;
}

:deep(blockquote) {
  margin: 0 0 16px 0;
  padding: 0 1em;
  color: #6a737d;
  border-left: 0.25em solid #dfe2e5;
}

:deep(table) {
  border-collapse: collapse;
  margin-bottom: 16px;
  width: 100%;
}

:deep(table th), :deep(table td) {
  border: 1px solid #dfe2e5;
  padding: 6px 13px;
}

:deep(table th) {
  background-color: #f6f8fa;
  font-weight: 600;
}

:deep(a) {
  color: #0366d6;
  text-decoration: none;
}

:deep(a:hover) {
  text-decoration: underline;
}

:deep(strong) {
  font-weight: 600;
}

:deep(em) {
  font-style: italic;
}

:deep(code) {
  background-color: #f6f8fa;
  border: 1px solid #e1e4e8;
  border-radius: 3px;
  font-size: 85%;
  margin: 0;
  padding: 0.2em 0.4em;
  font-family: 'SFMono-Regular', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', monospace;
  color: #e36209;
}

:deep(pre code) {
  background-color: transparent;
  border-radius: 0;
  font-size: 100%;
  margin: 0;
  padding: 0;
}

/* 打字机效果 */
:deep(.typing-cursor) {
  display: inline-block;
  animation: blink 1s infinite;
  color: #0366d6;
  font-weight: bold;
  margin-left: 2px;
}

@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* 流式代码块样式增强 */
:deep(pre.streaming) {
  border-left: 4px solid #0366d6;
  background: linear-gradient(90deg, #f6f8fa 0%, #f0f8ff 100%);
  position: relative;
}

:deep(pre.streaming::before) {
  content: "正在生成...";
  position: absolute;
  top: 8px;
  right: 8px;
  background: #0366d6;
  color: white;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 10px;
  font-weight: 500;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 0.7; }
  50% { opacity: 1; }
}

/* 多文件代码块区分样式 */
:deep(pre[data-lang="html"]) {
  border-left: 4px solid #e34c26;
}

:deep(pre[data-lang="css"]) {
  border-left: 4px solid #1572b6;
}

:deep(pre[data-lang="javascript"]) {
  border-left: 4px solid #f7df1e;
}

:deep(pre[data-lang="typescript"]) {
  border-left: 4px solid #3178c6;
}

:deep(pre[data-lang="python"]) {
  border-left: 4px solid #3776ab;
}

:deep(pre[data-lang="java"]) {
  border-left: 4px solid #ed8b00;
}

:deep(pre[data-lang="json"]) {
  border-left: 4px solid #000000;
}

/* 代码块标题显示 */
:deep(pre::after) {
  content: attr(data-lang);
  position: absolute;
  top: 8px;
  left: 12px;
  background: rgba(0, 0, 0, 0.1);
  color: #666;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  opacity: 0.7;
}
</style>
